#pragma once

namespace AVUI {

template <class T>
class TRefCountedPtr
{
public:
	TRefCountedPtr()
	{
		m_p = NULL;
	}
	TRefCountedPtr(T* p, bool addRef = true)
	{
		m_p = p;
		if (p != NULL && addRef)
			((Object*)p)->AddRef();
	}
    TRefCountedPtr(const TRefCountedPtr<T>& other)
    {
        m_p = other.m_p;

        if(m_p != NULL)
        {
            ((Object*)m_p)->AddRef();
        }
    }

	~TRefCountedPtr()
	{
		if (m_p != NULL)
			((Object*)m_p)->Release();
	}

    const T* get_Ptr() const 
    {
        return m_p;
    }

    T* const get_Ptr() 
    {
        return m_p;
    }

	operator T*() const
	{
		return m_p;
	}

	T& operator*() const
	{
		return *m_p;
	}

	T* operator->() const
	{
        return m_p;
	}
	bool operator!() const
	{
		return (m_p == NULL);
	}
	bool operator==(T* pT) const
	{
		return m_p == pT;
	}
    bool operator!=(T* pT) const
    {
        return m_p != pT;
    }

    T* operator=(const TRefCountedPtr<T>& p)
    {
        if(m_p == p.m_p)
        {
            return m_p;
        }

        if(m_p != NULL)
        {
            ((Object*)m_p)->Release();
            m_p = NULL;
        }

        m_p = (T*) p;

        if(m_p != NULL)
        {
            ((Object*)m_p)->AddRef();
        }

        return m_p;
    }

    T* operator=(T* p)
    {
        if(m_p == p)
        {
            return m_p;
        }

        if(m_p != NULL)
        {
            ((Object*)m_p)->Release();
            m_p = NULL;
        }

        m_p = p;

        if(m_p != NULL)
        {
            ((Object*)m_p)->AddRef();
        }

        return m_p;
    }

private:

	T* m_p;
};


typedef TRefCountedPtr<Object> ObjectPtr;

};
